﻿namespace HuwmanCode.Diagnostics

open System.Security
open System.Security.Permissions
open System.Runtime.InteropServices
open Microsoft.Win32.SafeHandles
open System.Runtime.ConstrainedExecution

[<AutoOpen>]
module internal NativeMethods =
    let TH32CS_SNAPPROCESS = 0x00000002
    
    [<Struct; StructLayout(LayoutKind.Sequential)>]
    type ProcessEntry32 =
        val mutable Size : int
        val mutable Usage : int
        val mutable ProcessID : int
        val mutable DefaultHeapID : nativeint
        val mutable ModuleID : int
        val mutable Threads : int
        val mutable ParentProcessID : int
        val mutable PriClassBase : int
        val mutable Flags : int
        [<MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)>]
        val mutable ExeFile : string

    [<DllImport("kernel32.dll", SetLastError = true)>]
    extern bool CloseHandle(nativeint handle);

    [<SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)>]
    [<SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)>]
    type internal ProcessHandle() =
        inherit SafeHandleZeroOrMinusOneIsInvalid(true)

        [<ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)>]
        override sh.ReleaseHandle() =
            CloseHandle(sh.handle)
    
    [<DllImport("kernel32.dll", SetLastError = true)>]
    extern ProcessHandle CreateToolhelp32Snapshot(int flags, int processID)
    
    [<DllImport("kernel32.dll", SetLastError = true)>]
    extern bool Process32First(ProcessHandle handle, ProcessEntry32& processEntry)

    [<DllImport("kernel32.dll", SetLastError = true)>]
    extern bool Process32Next(ProcessHandle handle, ProcessEntry32& processEntry)